﻿/*------------------------------------------------------------------------

SOLIDRD.HPP v1.0.0

Copyright 楊志賢 CxxlMan, 2013
All Rights Reserved

------------------------------------------------------------------------*/


#if !defined(__SOLIDRD_HPP_Cxxl3D)
#define __SOLIDRD_HPP_Cxxl3D

#include <MEMSTORAGE.HPP>
#include <Sys\IREBDERPIPE.HPP>
#include <Sys\C3DNODE.HPP>
#include <Sys\RENDERUNIT.HPP>
#include <Sys\RenderUnit\SYSDDCLASSID.HPP>
#include <Sys\RenderUnit\SysRenderDatagram\PRIMITIVERD.HPP>
#include <Sys\CSMART_PTR.HPP>
#include <Sys\VERTEXFMT.HPP>


namespace Cxxl3D
{

// ISolidRD 的屬性配置格式
struct tagISolidRD_Cfg
{ 
  unsigned char Light : 1; // 燈光 0=關 1=開
  unsigned char CullMode : 2; // 剔除不計算的面 0=不剔除 1=順時針方向 2=逆時針方向

  tagISolidRD_Cfg()
  {
    Light = 0;
    CullMode = 1;
  }
};

class ISolidRD:public IRenderDatagram,public IC3D_NodeHost,public IRDpkg
{
  // 這裡須傳回 IRenderDatagram 的 "實作介面"，即被 cxxlCM_GetElement() 叫用的 InterfaceID
  CxxlMan::UNICODE_String cxxlFASTCALL GetRenderDatagramID() const
  {
    return ISolid_ClassID;
  }

  // 傳回 IRenderDatagram 的 "實作介面"
  virtual void *cxxlFASTCALL GetDefaultInterface()
  {
    return this;
  }

protected:
  // 儲存容器藉此取得要永續存取的屬性資料
  // 延伸類別須以 virtual 的形式覆寫
  // 並且須呼叫上層類別的此函數
  virtual bool cxxlFASTCALL Ref(CxxlMan::Filter *F)
  {
    if(F != NULL && cxxlPreserve2::Ref(F))
      return true;
    else
      return false;
  }

  // Constructor
  ISolidRD()
    :cxxlObject(CxxlMan::Spirit_Easy),    
    CxxlMan::cxxlPreserve2(ISolid_ClassID), // 在建構時指定 ClassID
    IRDpkg(this)
  {
  }
  // Destructor
  virtual ~ISolidRD()
  {
  }

public:

  // 設定 IBasicPrimitiveRD 物件
  //virtual void cxxlFASTCALL SetIBasicPrimitiveRD(const CxxlMan::Smart_Ptr<IBasicPrimitiveRD> &IBasicPrimitiveRD_Arg) = 0;
  // 取得 IBasicPrimitiveRD 物件
  //virtual CxxlMan::Smart_Ptr<IBasicPrimitiveRD> cxxlFASTCALL GetIBasicPrimitiveRD() const = 0;

  virtual void cxxlFASTCALL SetCfg(const tagISolidRD_Cfg &Cfg) = 0;
  virtual tagISolidRD_Cfg cxxlFASTCALL GetCfg() = 0;

  // 保存永續儲存資料
  bool cxxlFASTCALL Save(const CxxlMan::Smart_Ptr<CxxlMan::IcxxlStorage> &IcxxlStorage_Arg, const CxxlMan::UNICODE_String &BackupName)
  {
    return IcxxlStorage_Arg->Save(CxxlMan::Smart_Ptr<ISolidRD>(this), BackupName);
  }

  // 取回永續儲存資料，並立即執行，若有錯誤原資料不變
  bool cxxlFASTCALL Load(const CxxlMan::Smart_Ptr<CxxlMan::IcxxlStorage> &IcxxlStorage_Arg, const CxxlMan::UNICODE_String &BackupName)
  {
    CxxlMan::Smart_Ptr<CxxlMan::IcxxlStorage> tmpStorage_Ptr(new CxxlMan::MemStorage);
    if(tmpStorage_Ptr->Save(CxxlMan::Smart_Ptr<ISolidRD>(this), L"Tmp") == false)
      return false;

    if(IcxxlStorage_Arg->Load(CxxlMan::Smart_Ptr<ISolidRD>(this), BackupName))
      return true;

    tmpStorage_Ptr->Load(CxxlMan::Smart_Ptr<ISolidRD>(this),L"Tmp");
    return false;
  }


  // 建立 ISolidND 物件，失敗傳回 NULL
  static CxxlMan::Smart_Ptr<ISolidRD> cxxlFASTCALL Create()
  {
    return CxxlMan::Preserve2_Cast<ISolidRD>( CxxlMan::cxxlCM_GetElement(ISolid_ClassID, IRenderDatagram_Group) );
  }

  // 從永存資料產生 ISolidRD 物件
  // 失敗傳回 NULL
  static CxxlMan::Smart_Ptr<ISolidRD> cxxlFASTCALL Create(const CxxlMan::UNICODE_String &BackupName, const CxxlMan::Smart_Ptr<CxxlMan::IcxxlStorage> &IcxxlStorage_Arg)
  {
    CxxlMan::Smart_Ptr<cxxlPreserve2> cxxlPreserve2_Ptr(NULL);
    CxxlMan::REGENERARETURN_TYPE rt = cxxlCM_Regenera(cxxlPreserve2_Ptr, BackupName, IcxxlStorage_Arg, true);

    if(rt == CxxlMan::Regenera_Success)
      return CxxlMan::Smart_Cast<ISolidRD>(cxxlPreserve2_Ptr);
    else
      return NULL;
  }


  friend class CxxlMan::IcxxlStorage;          // Preserve2 元件須加上這個
  friend class CxxlMan::Smart_Ptr<ISolidRD>;  // Preserve2 元件須加上這個
};

} /* namespace Cxxl3D */
#endif

